﻿#include "phnt/phnt_windows.h"
#include "phnt/phnt.h"
#include <iostream>

HANDLE SreachDLL(WCHAR*  dllName){
    auto peb = (PEB*)NtCurrentTeb()->ProcessEnvironmentBlock;
    // 获取Ldr并遍历InLoadOrderModuleList来查找模块
    if (peb && peb->Ldr) {
        PLIST_ENTRY moduleList = &peb->Ldr->InLoadOrderModuleList;
        PLIST_ENTRY entry = moduleList->Flink;

        while (entry != moduleList) {
            // 获取当前模块的LDR_DATA_TABLE_ENTRY结构
            PLDR_DATA_TABLE_ENTRY currentModule = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

            // 打印模块名称和基址
            std::wcout << "Module Name: " << currentModule->BaseDllName.Buffer << std::endl;
            std::wcout << "Base Address: " << currentModule->DllBase << std::endl;

            if(!wcscmp(currentModule->BaseDllName.Buffer,dllName)){
                return currentModule->DllBase;
            }

            // 继续下一个模块
            entry = entry->Flink;
        }
    } else {
        std::cerr << "Failed to retrieve PEB or PEB->Ldr is NULL." << std::endl;
    }
    return nullptr;
}

void * GetProcNameE(HANDLE hModule,const char *funName){
    // 假设DLL基地址已经获取到，例如通过加载DLL的句柄

    if (hModule == NULL) {
        std::cerr << "Failed to load DLL." << std::endl;
        return nullptr;
    }

    // 获取PE头指针
    PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)hModule;
    PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDOSHeader->e_lfanew);

    // 获取导出表的地址
    DWORD exportDirRVA = pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hModule + exportDirRVA);

    // 获取导出表的信息
    DWORD* pAddressOfFunctions = (DWORD*)((BYTE*)hModule + pExportDir->AddressOfFunctions);
    DWORD* pAddressOfNames = (DWORD*)((BYTE*)hModule + pExportDir->AddressOfNames);
    WORD* pAddressOfNameOrdinals = (WORD*)((BYTE*)hModule + pExportDir->AddressOfNameOrdinals);

    // 遍历所有导出函数
    for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
        char* functionName = (char*)((BYTE*)hModule + pAddressOfNames[i]);
        DWORD functionRVA = pAddressOfFunctions[pAddressOfNameOrdinals[i]];
        void* functionAddress = (BYTE*)hModule + functionRVA;
        if(!strcmp(functionName, funName)){
            std::cout << "Function Name: " << functionName << std::endl;
            std::cout << "Function Address: " << functionAddress << std::endl;
            return functionAddress;
        }
    }
    return nullptr;
}
#define CALL_API(hModule,func) ((decltype(func)*)GetProcNameE(hModule,#func))
int main(){

    HANDLE hModule = SreachDLL(L"KERNEL32.DLL");
    typedef HMODULE(WINAPI *LoadLibraryFunc)(LPCSTR lpLibFileName);
    typedef int(WINAPI *MessageBoxAFunc)(HWND hWnd,LPCSTR lpText, LPCSTR lpCaption,UINT uType);
     // 函数执行方法一；
    // void * pLoadLibraryA = GetProcNameE(hModule,"LoadLibraryA");
    //  HANDLE hUser32 =  ((LoadLibraryFunc)pLoadLibraryA)("user32.dll");
    //  void * pMessageBoxA = GetProcNameE(hUser32,"MessageBoxA");
    // ((MessageBoxAFunc)pMessageBoxA)(NULL,"hello","hello",0);

    // 函数执行方法二：
    // HANDLE hUser32 = ((decltype(LoadLibraryA)*)GetProcNameE(hModule,"LoadLibraryA"))("user32.dll");
    // ((decltype(MessageBoxA)*)GetProcNameE(hUser32,"MessageBoxA"))(NULL,"hello","hello",0);

    // 函数执行方法三：
    HANDLE hUser32 = CALL_API(hModule,LoadLibraryA)("user32.dll");
    CALL_API(hUser32,MessageBoxA)(NULL,"hello","hello",0);
    return 0;
}
